package com.tianci.appstore.controller.manager;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Environment;
import android.os.RemoteException;
import android.os.StatFs;

import com.coocaa.x.app.framework.app.LiteAppApplication;
import com.coocaa.x.app.framework.app.LiteAppApplication.ContentAppChangedReceiver.ContentAppChangedReceiverListener;
import com.coocaa.x.framework.utils.LiteURI;
import com.coocaa.x.framework.utils.LogUtils;
import com.coocaa.x.framework.utils.PMUtils.PackageMoveLocation;
import com.coocaa.x.service.XServiceManager;
import com.coocaa.x.service.litecontent.LiteContentServiceConnecter;
import com.coocaa.x.service.litecontent.data.apps.com_coocaa_app.AppData;
import com.coocaa.x.service.litecontent.data.apps.com_coocaa_app.RP_Installed_Apps;
import com.coocaa.x.service.litepm.aidl.ILitePMMoveAppListener;
import com.coocaa.x.service.litepm.data.AppInfo;
import com.skyworth.framework.skysdk.util.SdCardChecker;
import com.tianci.appstore.controller.AppStoreBaseController;
import com.tianci.appstore.dataprovider.AppDataProvider;
import com.tianci.appstore.ui.data.SkyListAppData;
import com.tianci.appstore.ui.data.SkyListAppData.ListType;
import com.tianci.appstore.ui.list.move.OnMoveStateChangeListener;
import com.tianci.appstore.utils.SkyConstants;
import com.tianci.appstore.utils.Tools;

public class MoveManagerController extends AppStoreBaseController implements
        ContentAppChangedReceiverListener

{

    private static MoveManagerController managerController = null;
    private static Context mContext = null;
    private List<SkyListAppData> mNativeApp = null;
    private List<SkyListAppData> mSdcardApp = null;
    private OnMoveStateChangeListener mStateChangeListener = null;
    private List<SkyListAppData> mWaitMoveList = new ArrayList<SkyListAppData>();
    private PackageMoveLocation mMoveLocation = null;

    public static MoveManagerController getInstance(Context mContext) {
        if (null == managerController)
            managerController = new MoveManagerController(mContext);
        return managerController;
    }

    public MoveManagerController(Context c) {
        mContext = c;
        mNativeApp = Collections.synchronizedList(new ArrayList<SkyListAppData>());
        mSdcardApp = Collections.synchronizedList(new ArrayList<SkyListAppData>());
        LiteAppApplication.addContentAppChangedReceiverListener(this);
        getAppsByLocation();
    }

    public void setMoveStateChangeListener(OnMoveStateChangeListener listener) {
        this.mStateChangeListener = listener;
        // refreshCountAndSpace();
    }

    public float getInstalledAppSpaceSize(PackageMoveLocation location) {
        List<SkyListAppData> appDatas = getListAppDatas(location);
        if (appDatas != null && appDatas.size() > 0) {
            float allSize = 0;
            long size = 0;
            for (SkyListAppData data : appDatas) {
                long appSize = data.getSize();
                size += appSize;
                allSize = (float) size / SkyConstants.KTOM;
                allSize = Tools.fixFloat(allSize);
            }
            return allSize;
        } else {
            return 0.0f;
        }
    }

    public int getInstallAppSize(PackageMoveLocation location) {
        return getListAppDatas(location).size();
    }

    public List<SkyListAppData> getListAppDatas(PackageMoveLocation location) {
        switch (location) {
            case EXTERNAL_MEDIA:
                return mSdcardApp;
            case INTERNAL_MEMORY:
                return mNativeApp;
            default:
                break;
        }
        return mNativeApp;
    }

    public void moveAppList(List<SkyListAppData> appDatas, PackageMoveLocation location) {
        LogUtils.d("the current location is " + location.toString());
        if (appDatas.size() > 0) {
            mFailedList.clear();
            mMoveLocation = getOtherLocation(location);
            LogUtils.d("the move location is " + mMoveLocation.toString());
            mWaitMoveList.addAll(appDatas);
            moveApp(mWaitMoveList.remove(0));
        }
    }

    public static String DiskSizeCount(long length) {
        int sub_index = 0;
        String show = "";
        if (length >= 1073741824) {
            sub_index = (String.valueOf((float) length / 1073741824)).indexOf(".");
            show = ((float) length / 1073741824 + "000").substring(0, sub_index + 3) + "GB";
        } else if (length >= 1048576) {
            sub_index = (String.valueOf((float) length / 1048576)).indexOf(".");
            show = ((float) length / 1048576 + "000").substring(0, sub_index + 3) + "MB";
        } else if (length >= 1024) {
            sub_index = (String.valueOf((float) length / 1024)).indexOf(".");
            show = ((float) length / 1024 + "000").substring(0, sub_index + 3) + "KB";
        } else if (length < 1024) {
            show = String.valueOf(length) + "B";
        }
        return show;
    }

    private PackageMoveLocation getOtherLocation(PackageMoveLocation location) {
        switch (location) {
            case EXTERNAL_MEDIA:
                return PackageMoveLocation.INTERNAL_MEMORY;
            case INTERNAL_MEMORY:
                return PackageMoveLocation.EXTERNAL_MEDIA;
            default:
                break;
        }
        return PackageMoveLocation.EXTERNAL_MEDIA;
    }

    public void moveApp(SkyListAppData datas) {
        mTempAppData = datas;
        try {
            XServiceManager.getLitePMService().movePackage(datas.getPkgName(),
                    mMoveLocation.toString(), moveAppStub);
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public List<SkyListAppData> getInstalledData(PackageMoveLocation location) {
        getAppsByLocation();
        switch (location) {
            case EXTERNAL_MEDIA:
                return mSdcardApp;
            case INTERNAL_MEMORY:
                return mNativeApp;
            default:
                break;
        }
        return null;
    }

    // public void refreshCountAndSpace()
    // {
    // if (mStateChangeListener != null)
    // {
    // mStateChangeListener.refreshCountAndSpace(mNativeApp.size(),
    // getInstalledAppSpaceSize(PackageMoveLocation.INTERNAL_MEMORY),
    // getAvailableInternalMemorySize(), PackageMoveLocation.INTERNAL_MEMORY);
    // }
    // }

    private List<SkyListAppData> formData(List<AppInfo> list) {
        List<SkyListAppData> ret = new ArrayList<SkyListAppData>();
        for (AppInfo info : list) {
            if (info.isSystemUserId)
                continue;
            SkyListAppData appInfo = new SkyListAppData(ListType.LOCAL_APP_LIST, "", info.appName,
                    "", info.pkgName);
            appInfo.setVersionName(String.valueOf(info.versionCode));
            appInfo.setMainActivity(info.mainActivity);
            long size = info.size / SkyConstants.BTOK;
            appInfo.setSize(size);
            float size2 = (float) size / SkyConstants.KTOM;
            if (size2 > 1.0f) {
                size2 = Tools.fixFloat(size2);
                appInfo.setShowInfo(String.valueOf(size2) + "MB");
            } else {
                appInfo.setShowInfo(String.valueOf(size) + "KB");
            }
            ret.add(appInfo);
        }
        return ret;
    }

    private void getAppsByLocation() {
        List<AppInfo> appinfos = getInstalledApps();
        final List<SkyListAppData> installedList = formData(appinfos);
        mNativeApp.clear();
        mSdcardApp.clear();
        if (installedList != null && installedList.size() > 0) {
            HashSet<String> classifySet = AppDataProvider.getInstance().getLocalData()
                    .getClassifyPkg();
            for (SkyListAppData data : installedList) {
                if (classifySet != null && classifySet.size() > 0) {
                    if (classifySet.contains(data.getPkgName())) {
                        continue;
                    }
                }
                LogUtils.d("the " + data.getTitle() + " size is " + data.getSize());
                if (getPackageInstalledLocation(data.getPkgName()).equals(
                        PackageMoveLocation.EXTERNAL_MEDIA)) {
                    mSdcardApp.add(data);
                } else {
                    mNativeApp.add(data);
                }
            }
        }
    }

    public PackageMoveLocation getPackageInstalledLocation(String pname) {
        PackageManager pm = mContext.getPackageManager();
        ApplicationInfo appInfo;
        try {
            appInfo = pm.getApplicationInfo(pname, 0);
            if ((appInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                return PackageMoveLocation.EXTERNAL_MEDIA;
            }
        } catch (NameNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return PackageMoveLocation.INTERNAL_MEMORY;
    }

    // 获取系统总内存
    public float getTotalInternalMemorySize() {
        File path = Environment.getDataDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSize();
        long totalBlocks = stat.getBlockCount();
        float size = (float) (totalBlocks * blockSize) / SkyConstants.BTOM;
        size = Tools.fixFloat(size);
        return size;
    }

    public boolean isSDCardAvaiable() {
        return SdCardChecker.isSDCardAvaiable();
    }

    public float getSDcardAvailableSpace() {
        return SdCardChecker.getSDCardAvailableStore() / SkyConstants.BTOM;
    }

    // 获取系统可用的总内存
    public float getAvailableInternalMemorySize() {
        File path = Environment.getDataDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSize();
        long availableBlocks = stat.getAvailableBlocks();
        float size = (float) (availableBlocks * blockSize) / SkyConstants.BTOM;
        size = Tools.fixFloat(size);
        return size;
    }

    @Override
    public void destroy() {
        mMoveLocation = null;
        mStateChangeListener = null;
        LiteAppApplication.removeContentAppChangedReceiverListener(this);
        mNativeApp.clear();
        mSdcardApp.clear();
        managerController = null;
    }

    private List<AppInfo> getInstalledApps() {
        LiteURI uri = LiteURI.create("apps://com.coocaa.app/installed_apps");
        uri.addParams("filter", "delete");
        String json = null;
        try {
            json = LiteContentServiceConnecter.getService().call(uri.toString());
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        List<AppInfo> appList = new ArrayList<AppInfo>();
        if (json != null) {
            RP_Installed_Apps rp = RP_Installed_Apps.parseJObject(json, RP_Installed_Apps.class);
            List<AppData> appdatas = rp.resource.resource_items;
            if (appdatas != null && appdatas.size() > 0) {
                for (AppData appdata : appdatas)
                    appList.add(appdata.info);
            }
        }
        return appList;
    }

    private synchronized void refreshAppDatas() {
        getAppsByLocation();
        if (mStateChangeListener != null) {
            mStateChangeListener.refreshAppDatas(mNativeApp, PackageMoveLocation.INTERNAL_MEMORY);
            mStateChangeListener.refreshAppDatas(mSdcardApp, PackageMoveLocation.EXTERNAL_MEDIA);
        }
    }

    private ILitePMMoveAppListener.Stub moveAppStub = new ILitePMMoveAppListener.Stub() {
        @Override
        public void onPackageMoved(String pname, String location, boolean success)
                throws RemoteException {
            // TODO Auto-generated method stub
            LogUtils.d(pname + " move " + success);
            if (!success) {
                mFailedList.add(mTempAppData);
            }
            if (mWaitMoveList.size() > 0) {
                moveApp(mWaitMoveList.remove(0));
            } else {
                refreshAppDatas();
                // refreshCountAndSpace();
                mStateChangeListener.refreshResult(mFailedList);
            }
        }
    };

    @Override
    public void onAction(Intent i) {
        refreshAppDatas();
    }

}
